<template>
  <b-modal id="modal-user" ref="modal" :title="modalTitle" @hidden="resetForm">
    <b-form id="form-user" novalidate @submit.prevent="handleSubmit">
      <b-container>
        <!-- Manual unlock form control -->
        <b-row v-if="!newUser && manualUnlockPolicy && user.Locked">
          <b-col sm="9">
            <alert :show="true" variant="warning" small>
              <template v-if="!v$.form.manualUnlock.$dirty">
                {{ i18n.t('pageUserManagement.modal.accountLocked') }}
              </template>
              <template v-else>
                {{
                  i18n.t('pageUserManagement.modal.clickSaveToUnlockAccount')
                }}
              </template>
            </alert>
          </b-col>
          <b-col sm="3">
            <input
              v-model="form.manualUnlock"
              data-test-id="userManagement-input-manualUnlock"
              type="hidden"
            />
            <b-button
              variant="primary"
              :disabled="v$.form.manualUnlock.$dirty"
              data-test-id="userManagement-button-manualUnlock"
              @click="v$.form.manualUnlock.$touch()"
            >
              {{ i18n.t('pageUserManagement.modal.unlock') }}
            </b-button>
          </b-col>
        </b-row>
        <b-row>
          <b-col>
            <b-form-group
              :label="i18n.t('pageUserManagement.modal.accountStatus')"
            >
              <b-form-radio
                v-model="form.status"
                name="user-status"
                :value="true"
                data-test-id="userManagement-radioButton-statusEnabled"
                @input="v$.form.status.$touch()"
              >
                {{ i18n.t('global.status.enabled') }}
              </b-form-radio>
              <b-form-radio
                v-model="form.status"
                name="user-status"
                data-test-id="userManagement-radioButton-statusDisabled"
                :value="false"
                :disabled="!newUser && originalUsername === disabled"
                @input="v$.form.status.$touch()"
              >
                {{ i18n.t('global.status.disabled') }}
              </b-form-radio>
            </b-form-group>
            <b-form-group
              :label="i18n.t('pageUserManagement.modal.username')"
              label-for="username"
            >
              <b-form-text id="username-help-block">
                {{ i18n.t('pageUserManagement.modal.cannotStartWithANumber') }}
                <br />
                {{
                  i18n.t(
                    'pageUserManagement.modal.noSpecialCharactersExceptUnderscore',
                  )
                }}
              </b-form-text>
              <b-form-input
                id="username"
                v-model="form.username"
                type="text"
                aria-describedby="username-help-block"
                data-test-id="userManagement-input-username"
                :state="getValidationState(v$.form.username)"
                :disabled="!newUser && originalUsername === disabled"
                @input="v$.form.username.$touch()"
              />
              <b-form-invalid-feedback role="alert">
                <template v-if="v$.form.username.required.$invalid">
                  {{ i18n.t('global.form.fieldRequired') }}
                </template>
                <template v-else-if="v$.form.username.maxLength.$invalid">
                  {{
                    i18n.t('global.form.lengthMustBeBetween', {
                      min: 1,
                      max: 16,
                    })
                  }}
                </template>
                <template v-else-if="v$.form.username.pattern.$invalid">
                  {{ i18n.t('global.form.invalidFormat') }}
                </template>
              </b-form-invalid-feedback>
            </b-form-group>
            <b-form-group
              :label="i18n.t('pageUserManagement.modal.privilege')"
              label-for="privilege"
            >
              <b-form-select
                id="privilege"
                v-model="form.privilege"
                :options="privilegeTypes"
                data-test-id="userManagement-select-privilege"
                :state="getValidationState(v$.form.privilege)"
                :disabled="!newUser && originalUsername === 'root'"
                @input="v$.form.privilege.$touch()"
              >
                <template #first>
                  <b-form-select-option :value="null" disabled>
                    {{ i18n.t('global.form.selectAnOption') }}
                  </b-form-select-option>
                </template>
              </b-form-select>
              <b-form-invalid-feedback role="alert">
                <template v-if="v$.form.privilege.required.$invalid">
                  {{ i18n.t('global.form.fieldRequired') }}
                </template>
              </b-form-invalid-feedback>
            </b-form-group>
          </b-col>
          <b-col>
            <b-form-group
              :label="i18n.t('pageUserManagement.modal.userPassword')"
              label-for="password"
            >
              <b-form-text id="password-help-block">
                {{
                  i18n.t('pageUserManagement.modal.passwordMustBeBetween', {
                    min: passwordRequirements.minLength,
                    max: passwordRequirements.maxLength,
                  })
                }}
              </b-form-text>
              <input-password-toggle>
                <b-form-input
                  id="password"
                  v-model="form.password"
                  type="password"
                  autocomplete="new-password"
                  data-test-id="userManagement-input-password"
                  aria-describedby="password-help-block"
                  :state="getValidationState(v$.form.password)"
                  class="form-control-with-button"
                  @input="v$.form.password.$touch()"
                />
                <b-form-invalid-feedback role="alert">
                  <template v-if="v$.form.password.required.$invalid">
                    {{ i18n.t('global.form.fieldRequired') }}
                  </template>
                  <template
                    v-if="
                      v$.form.password.minLength.$invalid ||
                      v$.form.password.maxLength.$invalid
                    "
                  >
                    {{
                      i18n.t('pageUserManagement.modal.passwordMustBeBetween', {
                        min: passwordRequirements.minLength,
                        max: passwordRequirements.maxLength,
                      })
                    }}
                  </template>
                </b-form-invalid-feedback>
              </input-password-toggle>
            </b-form-group>
            <b-form-group
              :label="i18n.t('pageUserManagement.modal.confirmUserPassword')"
              label-for="password-confirmation"
            >
              <input-password-toggle>
                <b-form-input
                  id="password-confirmation"
                  v-model="form.passwordConfirmation"
                  data-test-id="userManagement-input-passwordConfirmation"
                  type="password"
                  autocomplete="new-password"
                  :state="getValidationState(v$.form.passwordConfirmation)"
                  class="form-control-with-button"
                  @input="v$.form.passwordConfirmation.$touch()"
                />
                <b-form-invalid-feedback role="alert">
                  <template
                    v-if="v$.form.passwordConfirmation.required.$invalid"
                  >
                    {{ i18n.t('global.form.fieldRequired') }}
                  </template>
                  <template
                    v-else-if="
                      v$.form.passwordConfirmation.sameAsPassword.$invalid
                    "
                  >
                    {{ i18n.t('pageUserManagement.modal.passwordsDoNotMatch') }}
                  </template>
                </b-form-invalid-feedback>
              </input-password-toggle>
            </b-form-group>
          </b-col>
        </b-row>
      </b-container>
    </b-form>
    <template #footer="{ cancel }">
      <b-button
        variant="secondary"
        data-test-id="userManagement-button-cancel"
        @click="cancel()"
      >
        {{ i18n.t('global.action.cancel') }}
      </b-button>
      <b-button
        form="form-user"
        data-test-id="userManagement-button-submit"
        type="submit"
        variant="primary"
        @click="onOk"
      >
        <template v-if="newUser">
          {{ i18n.t('pageUserManagement.addUser') }}
        </template>
        <template v-else>
          {{ i18n.t('global.action.save') }}
        </template>
      </b-button>
    </template>
  </b-modal>
</template>

<script>
import {
  required,
  maxLength,
  minLength,
  requiredIf,
} from '@vuelidate/validators';
import { helpers, sameAs } from 'vuelidate/lib/validators';
import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
import { useVuelidate } from '@vuelidate/core';

import InputPasswordToggle from '@/components/Global/InputPasswordToggle';
import Alert from '@/components/Global/Alert';
import { useI18n } from 'vue-i18n';

export default {
  components: { Alert, InputPasswordToggle },
  mixins: [VuelidateMixin],
  props: {
    user: {
      type: Object,
      default: null,
    },
    passwordRequirements: {
      type: Object,
      required: true,
    },
  },
  emits: ['ok', 'hidden'],
  setup() {
    const i18n = useI18n();
    return {
      v$: useVuelidate(),
      i18n,
    };
  },
  data() {
    return {
      originalUsername: '',
      form: {
        status: true,
        username: '',
        privilege: null,
        password: '',
        passwordConfirmation: '',
        manualUnlock: false,
      },
      disabled: this.$store.getters['global/username'],
    };
  },
  computed: {
    modalTitle() {
      return this.newUser
        ? this.i18n.t('pageUserManagement.addUser')
        : this.i18n.t('pageUserManagement.editUser');
    },
    newUser() {
      return this.user ? false : true;
    },
    accountSettings() {
      return this.$store.getters['userManagement/accountSettings'];
    },
    manualUnlockPolicy() {
      return !this.accountSettings.accountLockoutDuration;
    },
    privilegeTypes() {
      return this.$store.getters['userManagement/accountRoles'];
    },
  },
  watch: {
    user: function (value) {
      if (value === null) return;
      this.originalUsername = value.username;
      this.form.username = value.username;
      this.form.status = value.Enabled;
      this.form.privilege = value.privilege;
    },
  },
  validations() {
    return {
      form: {
        status: {
          required,
        },
        username: {
          required,
          maxLength: maxLength(16),
          pattern: helpers.regex('pattern', /^([a-zA-Z_][a-zA-Z0-9_]*)/),
        },
        privilege: {
          required,
        },
        password: {
          required: requiredIf(function () {
            return this.requirePassword();
          }),
          minLength: minLength(this.passwordRequirements.minLength),
          maxLength: maxLength(this.passwordRequirements.maxLength),
        },
        passwordConfirmation: {
          required: requiredIf(function () {
            return this.requirePassword();
          }),
          sameAsPassword: sameAs('password'),
        },
        manualUnlock: {},
      },
    };
  },
  methods: {
    handleSubmit() {
      let userData = {};

      if (this.newUser) {
        this.v$.$touch();
        if (this.v$.$invalid) return;
        userData.username = this.form.username;
        userData.status = this.form.status;
        userData.privilege = this.form.privilege;
        userData.password = this.form.password;
      } else {
        if (this.v$.$invalid) return;
        userData.originalUsername = this.originalUsername;
        if (this.v$.form.status.$dirty) {
          userData.status = this.form.status;
        }
        if (this.v$.form.username.$dirty) {
          userData.username = this.form.username;
        }
        if (this.v$.form.privilege.$dirty) {
          userData.privilege = this.form.privilege;
        }
        if (this.v$.form.password.$dirty) {
          userData.password = this.form.password;
        }
        if (this.v$.form.manualUnlock.$dirty) {
          // If form manualUnlock control $dirty then
          // set user Locked property to false
          userData.locked = false;
        }
        if (Object.entries(userData).length === 1) {
          this.closeModal();
          return;
        }
      }

      this.$emit('ok', { isNewUser: this.newUser, userData });
      this.closeModal();
    },
    closeModal() {
      this.$nextTick(() => {
        this.$refs.modal.hide();
      });
    },
    resetForm() {
      this.form.originalUsername = '';
      this.form.status = true;
      this.form.username = '';
      this.form.privilege = null;
      this.form.password = '';
      this.form.passwordConfirmation = '';
      this.v$.$reset();
      this.$emit('hidden');
    },
    requirePassword() {
      if (this.newUser) return true;
      if (this.v$.form.password.$dirty) return true;
      if (this.v$.form.passwordConfirmation.$dirty) return true;
      return false;
    },
    onOk(bvModalEvt) {
      // prevent modal close
      bvModalEvt.preventDefault();
      this.handleSubmit();
    },
  },
};
</script>
